package cc.eddic.practice.concurrency.impl;

import cc.eddic.practice.concurrency.LogItem;
import cc.eddic.practice.concurrency.LogItemParser;
import lombok.extern.slf4j.Slf4j;
import lombok.val;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class LogItemParserScwImpl implements LogItemParser {

    /**
     * 解析日志项
     *
     * @param line 日志行
     * @return LogItem 可能为空
     * //
     */

    @Override
    public Optional<LogItem> parse(String line) {
        val m = LOG_PATTERN.matcher(line);
        if (!m.matches()) {
            log.error("Error parsing line: {}", line);
            return Optional.empty();
        }
        String ip = m.group("ip");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss Z", Locale.ENGLISH);
        LocalDateTime localDateTime = LocalDateTime.parse(m.group("dt"), formatter);
        String request = m.group("request");
        Matcher matcher = REQUEST_PATTERN.matcher(request);
        String method = null;
        String protocol = null;
        String url = null;
        if (matcher.matches()) {
            method = matcher.group("method");
            protocol = matcher.group("protocol");
            url = matcher.group("url");
        }
        int statues = Integer.parseInt(m.group("status"));
        long bytes = Long.parseLong(m.group("sent"));
        String referer = m.group("referer");
        String ua = m.group("ua");
        return Optional.of(new LogItem(ip, localDateTime, request, method, url, null, protocol, statues, bytes, referer, ua));
    }

    private static final Pattern LOG_PATTERN = Pattern.compile
            ("(?<ip>\\d+\\.\\d+\\.\\d+\\.\\d+)\\s+[\\w\\-]+\\s+[\\w\\-]+\\s+\\[" +
                    "(?<dt>\\d+/\\w+/\\d+:\\d+:\\d+:\\d+\\s+\\+\\d+)]\\s+\"" +
                    "(?<request>.*)\"\\s+" +
                    "(?<status>\\d+)\\s+" +
                    "(?<sent>\\d+)\\s+\"" +
                    "(?<referer>[^\"]+)\"\\s+\"" +
                    "(?<ua>[^\"]+)\"");
    private static final Pattern REQUEST_PATTERN = Pattern.compile("(?<method>\\w+)\\s+(?<url>[^ ]+)\\s+(?<protocol>[^ ]+)");
}
